#include "pd_policy_engine.h"
#include "pd_core.h"
#include "pd_dpm_core.h"
#include "tcpci_event.h"
#include "tcpci_core.h"
#include "tcpci_timer.h"
#include "tcpm.h"

#undef LOG_TAG
#define LOG_TAG    "pd_policy_engine_snk"
#include "elog.h"

//bool __pd_put_pe_event(	struct sgm41620_tcpc *tcpc_dev, uint8_t pe_event);
//extern struct sgm41620_tcpc g_tcpc_dev;
/*
 * [PD2.0] Figure 8-39 Sink Port state diagram
 */


void pe_snk_startup_entry(struct pd_port *pd_port)
{
	//log_i("pe_snk_startup_entry\r\n" );
	uint8_t rx_cap = PD_RX_CAP_PE_STARTUP;
	bool pr_swap = pd_port->state_machine == PE_STATE_MACHINE_PR_SWAP;
#if CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP
	uint8_t msg_id_last = pd_port->pe_data.msg_id_rx[TCPC_TX_SOP];
#endif	/* CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP */

	pd_reset_protocol_layer(pd_port, false);

	if (pr_swap) {
		/*
		 * If PE reset rx_cap to startup in here,
		 * maybe can't meet tSwapSink for PR_SWAP case
		 */
		rx_cap = PD_RX_CAP_PE_SEND_WAIT_CAP;

#if CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP
		pd_port->msg_id_pr_swap_last = msg_id_last;
#endif	/* CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP */
	}

	pd_set_rx_enable(pd_port, rx_cap);
	//log_i("snk_startup :put pe_reset!!!\r\n");
	pd_put_pe_event(pd_port, PD_PE_RESET_PRL_COMPLETED);
}

void pe_snk_discovery_entry(struct pd_port *pd_port)
{
	if (pd_check_pe_during_hard_reset(p_pd_port)) {
		pd_set_rx_enable(pd_port, PD_RX_CAP_PE_SEND_WAIT_CAP);
		pd_enable_vbus_safe0v_detection(p_pd_port);
		pd_enable_pe_state_timer(pd_port, PD_TIMER_HARD_RESET_SAFE0V);
	} else {
		pd_enable_vbus_valid_detection(p_pd_port, true);
	}
}

void pe_snk_wait_for_capabilities_entry(
				struct pd_port *pd_port)
{
	log_i("pe_snk_wait_for_capabilities_entry\r\n" );
	/* Default current draw after HardReset */
	if (pd_check_pe_during_hard_reset(pd_port))
		pd_dpm_sink_vbus(pd_port, true);

	pd_notify_pe_hard_reset_completed(pd_port);

	pd_set_rx_enable(pd_port, PD_RX_CAP_PE_SEND_WAIT_CAP);
	pd_enable_pe_state_timer(pd_port, PD_TIMER_SINK_WAIT_CAP);
}

void pe_snk_evaluate_capability_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_evaluate_capability_entry\r\n" );
	pd_handle_hard_reset_recovery(pd_port);
	pd_handle_first_pd_command(pd_port);
	pd_dpm_snk_evaluate_caps(pd_port);
	pd_port->pe_data.explicit_contract = false;
}

/*code for USB IF Start*/
/*int i2c_write_input_limit_charger_enter(void) {
    struct i2c_adapter *adapter;
    struct i2c_msg msg;
    int ret;
    u8 buf[2] = {0x0d, 0x03};

    adapter = i2c_get_adapter(5); // I2C1
    if (!adapter) {
        printk(KERN_ERR "Failed to get I2C adapter\n");
        return -ENODEV;
    }

    msg.addr = 0x6B; // 7-bit address, left-shifted to 8-bit format
    msg.flags = 0;
    msg.len = 2;
    msg.buf = buf;

    ret = i2c_transfer(adapter, &msg, 1);
    if (ret != 1) {
        printk(KERN_ERR "I2C transfer failed: %d\n", ret);
        i2c_put_adapter(adapter);
        return -EIO;
    }

    i2c_put_adapter(adapter);

    printk(KERN_INFO "ENTER 5V 0A successful\n");
    return 0;
}

int i2c_write_input_limit_charger_exit(void) {
    struct i2c_adapter *adapter;
    struct i2c_msg msg;
    int ret;
    u8 buf[2] = {0x0d, 0x00};

    adapter = i2c_get_adapter(5); // I2C1
    if (!adapter) {
        printk(KERN_ERR "Failed to get I2C adapter\n");
        return -ENODEV;
    }

    msg.addr = 0x6B; // 7-bit address, left-shifted to 8-bit format
    msg.flags = 0;
    msg.len = 2;
    msg.buf = buf;

    ret = i2c_transfer(adapter, &msg, 1);
    if (ret != 1) {
        printk(KERN_ERR "I2C transfer failed: %d\n", ret);
        i2c_put_adapter(adapter);
        return -EIO;
    }

    i2c_put_adapter(adapter);

    printk(KERN_INFO "EXIT 5V 0A successful successful\n");
    return 0;
}*/
/*code for USB IF END*/
/*static void usbif_disable_charger_func()
{
	//i2c_write_input_limit_charger_enter();
	//msleep(800);
	//i2c_write_input_limit_charger_exit();
}*/


void pe_snk_select_capability_entry(struct pd_port *pd_port)
{
	struct pd_event *pd_event = pd_get_curr_pd_event(pd_port);

    //log_i("pe_snk_select_capability_entry\r\n" );
	//INIT_DELAYED_WORK(&discharger_work, usbif_disable_charger_func);

	PE_STATE_WAIT_MSG_HRESET_IF_TOUT(pd_port);

	if (pd_event->event_type == PD_EVT_DPM_MSG) {
		/*log_i("SelectCap%d, rdo:0x%08x\n",
			pd_event->msg_sec, pd_port->last_rdo);*/
	} else {
		/* new request, for debug only */
		/* pd_dpm_sink_vbus(pd_port, false); */
		log_i("NewReq, rdo:0x%08x\n", pd_port->last_rdo);
	}

	pd_send_sop_data_msg(PD_DATA_REQUEST, 1, &pd_port->last_rdo); 
	if(pd_port->request_v_new == TCPC_VBUS_SINK_5V){
		//schedule_delayed_work(&discharger_work, 0);
		//to do
	}

	if(pd_port->request_v_new == 9000){
		//schedule_delayed_work(&discharger_work, 0);
		//to do
	}  
}

void pe_snk_select_capability_exit(struct pd_port *pd_port)
{
	//log_i("pe_snk_select_capability_exit\r\n" );
	if (pd_check_ctrl_msg_event(pd_port, PD_CTRL_ACCEPT))
		pd_port->pe_data.selected_cap = RDO_POS(pd_port->last_rdo);
	else if (pd_check_ctrl_msg_event(pd_port, PD_CTRL_REJECT))
		pd_port->pe_data.request_rejected = true;
}

void pe_snk_transition_sink_entry(struct pd_port *pd_port)
{
	//log_i("pe_snk_transition_sink_entry\r\n" );
	pd_enable_pe_state_timer(pd_port, PD_TIMER_PS_TRANSITION);

#if CONFIG_USB_PD_SNK_GOTOMIN
	if (pd_check_ctrl_msg_event(pd_port, PD_CTRL_GOTO_MIN)) {
		if (pd_port->dpm_caps & DPM_CAP_LOCAL_GIVE_BACK)
			pd_port->request_i_new = pd_port->request_i_op;
	}
#endif	/* CONFIG_USB_PD_SNK_GOTOMIN */
	
	//pd_dpm_snk_standby_power(pd_port);
}

void pe_snk_ready_entry(struct pd_port *pd_port)
{
	//log_i("pe_snk_ready_entry\r\n" );
	if (pd_port->state_machine == PE_STATE_MACHINE_NORMAL &&
	    pd_check_ctrl_msg_event(pd_port, PD_CTRL_WAIT)){
		
		log_i("PD_TIMER_SINK_REQUEST\r\n" );
		pd_enable_timer(pd_port, PD_TIMER_SINK_REQUEST);
		}
		
	pd_notify_pe_snk_explicit_contract(pd_port);
	pe_power_ready_entry(pd_port);
}

void pe_snk_hard_reset_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_hard_reset_entry\r\n" );
	pd_send_hard_reset(pd_port);
}

void pe_snk_transition_to_default_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_transition_to_default_entry\r\n" );
	pd_reset_local_hw(pd_port);
	pd_dpm_snk_hard_reset(pd_port);
}

void pe_snk_give_sink_cap_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_give_sink_cap_entry\r\n" );
	PE_STATE_WAIT_TX_SUCCESS(pd_port);
	pd_dpm_send_sink_caps(pd_port);
}

void pe_snk_get_source_cap_entry(struct pd_port *pd_port)
{
#if CONFIG_USB_PD_TCPM_CB_2ND
	PE_STATE_WAIT_MSG(pd_port);
#else
	PE_STATE_WAIT_TX_SUCCESS(pd_port);
#endif	/* CONFIG_USB_PD_TCPM_CB_2ND */

	pd_send_sop_ctrl_msg(PD_CTRL_GET_SOURCE_CAP);
}

void pe_snk_send_soft_reset_entry(struct pd_port *pd_port)
{
	pd_send_soft_reset(pd_port);
}

void pe_snk_soft_reset_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_soft_reset_entry\r\n" );
	pd_handle_soft_reset(pd_port);
}

/* ---- Policy Engine (PD30) ---- */

#if CONFIG_USB_PD_REV30

/*
 * [PD3.0] Figure 8-71 Sink Port Not Supported Message State Diagram
 */

void pe_snk_send_not_supported_entry(struct pd_port *pd_port)
{
	PE_STATE_WAIT_TX_SUCCESS(pd_port);

	pd_send_sop_ctrl_msg(PD_CTRL_NOT_SUPPORTED);
}

void pe_snk_not_supported_received_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_not_supported_received_entry\r\n" );
	PE_STATE_DPM_INFORMED(pd_port);

	pd_dpm_inform_not_support(pd_port);
}

void pe_snk_chunk_received_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_chunk_received_entry\r\n" );
	pd_enable_timer(pd_port, PD_TIMER_CK_NOT_SUPPORTED);
}

/*
 * [PD3.0] Figure 8-74 Sink Port Source Alert State Diagram
 */

#if CONFIG_USB_PD_REV30_ALERT_REMOTE
void pe_snk_source_alert_received_entry(struct pd_port *pd_port)
{
	PE_STATE_DPM_INFORMED(pd_port);

	pd_dpm_inform_alert(pd_port);
}
#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */

/*
 * [PD3.0] Figure 8-75 Sink Port Sink Alert State Diagram
 */

#if CONFIG_USB_PD_REV30_ALERT_LOCAL
void pe_snk_send_sink_alert_entry(struct pd_port *pd_port)
{
	PE_STATE_WAIT_TX_SUCCESS(pd_port);
	pd_dpm_send_alert(pd_port);
}
#endif	/* CONFIG_USB_PD_REV30_ALERT_REMOTE */

/*
 * [PD3.0] Figure 8-77 Sink Port Get Source Capabilities Extended State Diagram
 */

#if CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE
void pe_snk_get_source_cap_ext_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_get_source_cap_ext_entry\r\n" );
	PE_STATE_WAIT_MSG(pd_port);
	pd_send_sop_ctrl_msg(PD_CTRL_GET_SOURCE_CAP_EXT);
}

void pe_snk_get_source_cap_ext_exit(struct pd_port *pd_port)
{
	
	pd_dpm_inform_source_cap_ext(pd_port);
}

#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_REMOTE */

/*
 * [PD3.0] Figure 8-79 Sink Port Get Source Status State Diagram
 */

#if CONFIG_USB_PD_REV30_STATUS_REMOTE
void pe_snk_get_source_status_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_get_source_status_entry\r\n" );
	PE_STATE_WAIT_MSG(pd_port);
	pd_send_sop_ctrl_msg(PD_CTRL_GET_STATUS);
}

void pe_snk_get_source_status_exit(struct pd_port *pd_port)
{
	log_i("pe_snk_get_source_status_exit\r\n" );
	pd_dpm_inform_status(pd_port);
}

#endif	/* CONFIG_USB_PD_REV30_STATUS_REMOTE */

/*
 * [PD3.0] Figure 8-82 Sink Give Sink Status State Diagram
 */

#if CONFIG_USB_PD_REV30_STATUS_LOCAL
void pe_snk_give_sink_status_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_give_sink_status_entry\r\n" );
	PE_STATE_WAIT_TX_SUCCESS(pd_port);

	pd_dpm_send_status(pd_port);
}
#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */

/*
 * [PD3.0] Figure 8-83 Sink Port Get Source PPS Status State Diagram
 */

#if CONFIG_USB_PD_REV30_PPS_SINK
void pe_snk_get_pps_status_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_get_pps_status_entry\r\n" );
	PE_STATE_WAIT_MSG(pd_port);
	pd_send_sop_ctrl_msg(PD_CTRL_GET_PPS_STATUS);
}

void pe_snk_get_pps_status_exit(struct pd_port *pd_port)
{
	log_i("pe_snk_get_pps_status_exit\r\n" );
	pd_dpm_inform_pps_status(pd_port);
}
#endif	/* CONFIG_USB_PD_REV30_PPS_SINK */

void pe_snk_give_sink_cap_ext_entry(struct pd_port *pd_port)
{
	log_i("pe_snk_give_sink_cap_ext_entry\r\n" );
	PE_STATE_WAIT_TX_SUCCESS(pd_port);
	pd_dpm_send_sink_cap_ext(pd_port);
}

#endif	/* CONFIG_USB_PD_REV30 */
